# -*- coding: utf-8 -*-
"""
学习打卡服务层
目的：封装学习打卡相关的业务逻辑，提供统一的打卡操作接口
职责：处理科目管理、打卡记录、统计计算等核心业务逻辑
"""
from datetime import datetime, date, timedelta
from typing import Optional, Dict, Any, List
from sqlalchemy.orm import Session
from sqlalchemy import func, and_, or_, desc
from app.models.study_subject import StudySubject
from app.models.study_check_in import StudyCheckIn
from app.models.study_statistics import StudyStatistics
from app.config.database import SessionLocal
from app.utils.response import Result
from app.dto.study_dto import (
    CreateSubjectRequest, UpdateSubjectRequest,
    CheckInRequest, UpdateCheckInRequest,
    GetCheckInsListRequest, GetStatisticsRequest, GetCalendarRequest
)
from app.utils.datetime_utils import get_db_today, get_db_now


class StudyService:
    """
    学习打卡业务逻辑服务类
    目的：提供学习打卡相关的所有业务操作，将业务逻辑与控制器层解耦
    职责：科目CRUD、打卡记录管理、统计数据计算、日历数据生成
    使用场景：所有学习打卡相关的业务操作都通过此服务类处理
    """

    # ==================== 科目管理相关方法 ====================

    @staticmethod
    def create_subject(request: CreateSubjectRequest) -> Result:
        """
        创建学习科目
        目的：处理科目创建的业务逻辑，包括数据验证和存储
        功能：验证必填字段、创建科目记录并返回结果

        Args:
            request (CreateSubjectRequest): 创建科目请求对象

        Returns:
            Result: 统一响应结果对象
        """
        # 创建数据库会话对象，用于执行数据库操作
        db: Session = SessionLocal()

        try:
            # 验证科目名称是否为空
            if not request.name or not request.name.strip():
                return Result.validation_error('科目名称不能为空')

            # 验证用户是否已存在同名科目
            existing_subject = db.query(StudySubject).filter(
                StudySubject.user_id == request.user_id,
                StudySubject.name == request.name.strip(),
                StudySubject.status == 1  # 只检查启用状态的科目
            ).first()

            if existing_subject:
                return Result.validation_error(f'科目"{request.name}"已存在')

            # 创建科目对象
            subject = StudySubject(
                name=request.name.strip(),
                description=request.description,
                icon=request.icon,
                color=request.color or '#1890ff',
                target_days=request.target_days or 0,
                user_id=request.user_id,
                is_public=request.is_public or 0,
                sort_order=request.sort_order or 0,
                status=1  # 默认启用
            )

            # 保存到数据库
            db.add(subject)
            db.commit()
            db.refresh(subject)

            return Result.success(data=subject.to_dict(), message='科目创建成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'科目创建失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def update_subject(request: UpdateSubjectRequest) -> Result:
        """
        更新学习科目
        目的：更新已有科目的信息
        功能：验证权限、更新科目字段

        Args:
            request (UpdateSubjectRequest): 更新科目请求对象

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 查询科目是否存在
            subject = db.query(StudySubject).filter(
                StudySubject.id == request.subject_id
            ).first()

            if not subject:
                return Result.not_found('科目不存在')

            # 验证权限：只有科目创建者才能修改
            if subject.user_id != request.user_id:
                return Result.forbidden('无权限修改此科目')

            # 更新字段（只更新非None的字段）
            if request.name is not None:
                # 检查新名称是否与其他科目重复
                existing = db.query(StudySubject).filter(
                    StudySubject.user_id == request.user_id,
                    StudySubject.name == request.name.strip(),
                    StudySubject.id != request.subject_id,
                    StudySubject.status == 1
                ).first()
                if existing:
                    return Result.validation_error(f'科目"{request.name}"已存在')
                subject.name = request.name.strip()

            if request.description is not None:
                subject.description = request.description
            if request.icon is not None:
                subject.icon = request.icon
            if request.color is not None:
                subject.color = request.color
            if request.target_days is not None:
                subject.target_days = request.target_days
            if request.is_public is not None:
                subject.is_public = request.is_public
            if request.sort_order is not None:
                subject.sort_order = request.sort_order
            if request.status is not None:
                subject.status = request.status

            db.commit()
            db.refresh(subject)

            return Result.success(data=subject.to_dict(), message='科目更新成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'科目更新失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def delete_subject(subject_id: int, user_id: int) -> Result:
        """
        删除学习科目（软删除）
        目的：禁用科目，不实际删除数据
        功能：验证权限、将科目状态设为禁用

        Args:
            subject_id (int): 科目ID
            user_id (int): 用户ID，用于权限验证

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 查询科目
            subject = db.query(StudySubject).filter(
                StudySubject.id == subject_id
            ).first()

            if not subject:
                return Result.not_found('科目不存在')

            # 验证权限
            if subject.user_id != user_id:
                return Result.forbidden('无权限删除此科目')

            # 软删除：将状态设为禁用
            subject.status = 0
            db.commit()

            return Result.success(message='科目删除成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'科目删除失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def get_subject_by_id(subject_id: int, user_id: Optional[int] = None) -> Result:
        """
        获取科目详情
        目的：查询指定ID的科目信息
        功能：支持权限验证（私有科目只能创建者查看）

        Args:
            subject_id (int): 科目ID
            user_id (Optional[int]): 用户ID，用于私有科目权限验证

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            subject = db.query(StudySubject).filter(
                StudySubject.id == subject_id
            ).first()

            if not subject:
                return Result.not_found('科目不存在')

            # 权限验证：私有科目只能创建者查看
            if subject.is_public == 0 and user_id != subject.user_id:
                return Result.forbidden('无权限查看此科目')

            return Result.success(data=subject.to_dict())

        except Exception as e:
            return Result.internal_error(f'查询失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def get_subjects_list(user_id: int, include_public: bool = False) -> Result:
        """
        获取科目列表
        目的：查询用户的所有科目
        功能：支持查询自己的科目和公开科目

        Args:
            user_id (int): 用户ID
            include_public (bool): 是否包含公开科目

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 构建查询条件
            if include_public:
                # 查询自己的科目或公开科目
                query = db.query(StudySubject).filter(
                    or_(
                        StudySubject.user_id == user_id,
                        StudySubject.is_public == 1
                    ),
                    StudySubject.status == 1  # 只查启用的科目
                )
            else:
                # 只查询自己的科目
                query = db.query(StudySubject).filter(
                    StudySubject.user_id == user_id,
                    StudySubject.status == 1
                )

            # 按排序顺序和创建时间排序
            subjects = query.order_by(
                StudySubject.sort_order.asc(),
                StudySubject.created_at.desc()
            ).all()

            # 转换为字典列表
            subjects_data = [subject.to_dict() for subject in subjects]

            return Result.success(data=subjects_data)

        except Exception as e:
            return Result.internal_error(f'查询失败：{str(e)}')

        finally:
            db.close()

    # ==================== 打卡记录相关方法 ====================

    @staticmethod
    def check_in(request: CheckInRequest) -> Result:
        """
        每日打卡
        目的：记录用户的学习打卡
        功能：防重复打卡、记录打卡信息、更新统计数据

        Args:
            request (CheckInRequest): 打卡请求对象

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 验证科目是否存在且可用
            subject = db.query(StudySubject).filter(
                StudySubject.id == request.subject_id,
                StudySubject.status == 1
            ).first()

            if not subject:
                return Result.validation_error('科目不存在或已被禁用')

            # 验证权限：只能为自己的科目或公开科目打卡
            if subject.user_id != request.user_id and subject.is_public == 0:
                return Result.forbidden('无权限为此科目打卡')

            # 验证心情值范围
            if request.mood is not None and not (1 <= request.mood <= 5):
                return Result.validation_error('心情值必须在1-5之间')

            # 检查当天是否已打卡（数据库唯一约束会自动防止，但提前检查可以给出更友好的提示）
            # 使用数据库当前日期确保时区一致
            db_today = get_db_today()
            print(f"[DEBUG] 请求打卡日期: {request.check_in_date}, 数据库今天: {db_today}, 是否同一天: {request.check_in_date == db_today}")

            if request.check_in_date == db_today:
                existing = db.query(StudyCheckIn).filter(
                    StudyCheckIn.user_id == request.user_id,
                    StudyCheckIn.subject_id == request.subject_id,
                    StudyCheckIn.check_in_date == request.check_in_date,
                    StudyCheckIn.status == 1
                ).first()
            else:
                existing = None

            if existing:
                return Result.validation_error(f'今天已为"{subject.name}"打过卡了')

            # 创建打卡记录 - 使用数据库时间确保一致性
            db_time = get_db_now()
            check_in = StudyCheckIn(
                user_id=request.user_id,
                subject_id=request.subject_id,
                check_in_date=request.check_in_date,
                duration_minutes=request.duration_minutes,
                content=request.content,
                mood=request.mood,
                location_id=request.location_id,
                images=','.join(request.images) if request.images else None,
                status=1,
                created_at=db_time,  # 显式设置创建时间
                updated_at=db_time   # 显式设置更新时间
            )

            db.add(check_in)
            db.commit()
            db.refresh(check_in)

            # 更新统计数据（异步或同步）
            StudyService._update_statistics(db, request.user_id, request.subject_id, request.check_in_date)

            return Result.success(data=check_in.to_dict(), message='打卡成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'打卡失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def _update_statistics(db: Session, user_id: int, subject_id: int, check_in_date: date):
        """
        更新统计数据（内部方法）
        目的：在打卡后更新或创建统计记录
        功能：计算连续打卡天数、更新统计数据

        Args:
            db (Session): 数据库会话
            user_id (int): 用户ID
            subject_id (int): 科目ID
            check_in_date (date): 打卡日期
        """
        try:
            # 查询或创建统计记录
            stat = db.query(StudyStatistics).filter(
                StudyStatistics.user_id == user_id,
                StudyStatistics.subject_id == subject_id,
                StudyStatistics.stat_date == check_in_date
            ).first()

            # 计算当天该科目的打卡次数和总时长
            check_ins = db.query(StudyCheckIn).filter(
                StudyCheckIn.user_id == user_id,
                StudyCheckIn.subject_id == subject_id,
                StudyCheckIn.check_in_date == check_in_date,
                StudyCheckIn.status == 1
            ).all()

            check_in_count = len(check_ins)
            total_duration = sum(ci.duration_minutes or 0 for ci in check_ins)

            # 计算连续打卡天数
            continuous_days = StudyService._calculate_continuous_days(
                db, user_id, subject_id, check_in_date
            )

            if stat:
                # 更新已有统计
                stat.check_in_count = check_in_count
                stat.total_duration = total_duration
                stat.continuous_days = continuous_days
                stat.max_continuous_days = max(stat.max_continuous_days, continuous_days)
            else:
                # 创建新统计
                stat = StudyStatistics(
                    user_id=user_id,
                    subject_id=subject_id,
                    stat_date=check_in_date,
                    check_in_count=check_in_count,
                    total_duration=total_duration,
                    continuous_days=continuous_days,
                    max_continuous_days=continuous_days
                )
                db.add(stat)

            db.commit()

        except Exception as e:
            print(f"更新统计数据失败: {str(e)}")
            # 统计更新失败不影响打卡主流程，只记录日志

    @staticmethod
    def _calculate_continuous_days(db: Session, user_id: int, subject_id: int, current_date: date) -> int:
        """
        计算连续打卡天数（内部方法）
        目的：从当前日期往前推算连续打卡的天数
        功能：查询历史打卡记录，计算连续天数

        Args:
            db (Session): 数据库会话
            user_id (int): 用户ID
            subject_id (int): 科目ID
            current_date (date): 当前日期

        Returns:
            int: 连续打卡天数
        """
        continuous_days = 1  # 包含当天
        check_date = current_date - timedelta(days=1)

        # 往前查找连续的打卡记录
        while True:
            exists = db.query(StudyCheckIn).filter(
                StudyCheckIn.user_id == user_id,
                StudyCheckIn.subject_id == subject_id,
                StudyCheckIn.check_in_date == check_date,
                StudyCheckIn.status == 1
            ).first()

            if not exists:
                break

            continuous_days += 1
            check_date -= timedelta(days=1)

        return continuous_days

    @staticmethod
    def update_check_in(request: UpdateCheckInRequest) -> Result:
        """
        更新打卡记录
        目的：修改已有打卡记录的信息
        功能：验证权限、更新打卡字段

        Args:
            request (UpdateCheckInRequest): 更新打卡请求对象

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 查询打卡记录
            check_in = db.query(StudyCheckIn).filter(
                StudyCheckIn.id == request.check_in_id
            ).first()

            if not check_in:
                return Result.not_found('打卡记录不存在')

            # 验证权限
            if check_in.user_id != request.user_id:
                return Result.forbidden('无权限修改此打卡记录')

            # 更新字段
            if request.duration_minutes is not None:
                check_in.duration_minutes = request.duration_minutes
            if request.content is not None:
                check_in.content = request.content
            if request.mood is not None:
                if not (1 <= request.mood <= 5):
                    return Result.validation_error('心情值必须在1-5之间')
                check_in.mood = request.mood
            if request.location_id is not None:
                check_in.location_id = request.location_id
            if request.images is not None:
                check_in.images = ','.join(request.images) if request.images else None

            db.commit()
            db.refresh(check_in)

            # 更新统计数据（如果更新了时长）
            if request.duration_minutes is not None:
                StudyService._update_statistics(
                    db, check_in.user_id, check_in.subject_id, check_in.check_in_date
                )

            return Result.success(data=check_in.to_dict(), message='打卡记录更新成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'更新失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def delete_check_in(check_in_id: int, user_id: int) -> Result:
        """
        删除打卡记录（软删除）
        目的：将打卡记录标记为已删除
        功能：验证权限、软删除打卡记录、更新统计

        Args:
            check_in_id (int): 打卡记录ID
            user_id (int): 用户ID

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 查询打卡记录
            check_in = db.query(StudyCheckIn).filter(
                StudyCheckIn.id == check_in_id
            ).first()

            if not check_in:
                return Result.not_found('打卡记录不存在')

            # 验证权限
            if check_in.user_id != user_id:
                return Result.forbidden('无权限删除此打卡记录')

            # 软删除
            check_in.status = 0
            db.commit()

            # 更新统计数据
            StudyService._update_statistics(
                db, check_in.user_id, check_in.subject_id, check_in.check_in_date
            )

            return Result.success(message='打卡记录删除成功')

        except Exception as e:
            db.rollback()
            return Result.internal_error(f'删除失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def get_check_in_by_id(check_in_id: int, user_id: int) -> Result:
        """
        获取打卡记录详情
        目的：查询指定ID的打卡记录
        功能：验证权限、返回完整打卡信息

        Args:
            check_in_id (int): 打卡记录ID
            user_id (int): 用户ID

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            check_in = db.query(StudyCheckIn).filter(
                StudyCheckIn.id == check_in_id,
                StudyCheckIn.status == 1
            ).first()

            if not check_in:
                return Result.not_found('打卡记录不存在')

            # 验证权限（只能查看自己的打卡记录）
            if check_in.user_id != user_id:
                return Result.forbidden('无权限查看此打卡记录')

            return Result.success(data=check_in.to_dict(include_content=True))

        except Exception as e:
            return Result.internal_error(f'查询失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def get_check_ins_list(request: GetCheckInsListRequest) -> Result:
        """
        获取打卡记录列表（分页）
        目的：查询用户的打卡记录，支持多种筛选条件
        功能：分页查询、日期范围筛选、科目筛选、心情筛选

        Args:
            request (GetCheckInsListRequest): 查询请求对象

        Returns:
            Result: 统一响应结果对象，包含分页数据
        """
        db: Session = SessionLocal()

        try:
            # 构建基础查询
            query = db.query(StudyCheckIn).filter(
                StudyCheckIn.user_id == request.user_id,
                StudyCheckIn.status == request.status
            )

            # 科目筛选
            if request.subject_id:
                query = query.filter(StudyCheckIn.subject_id == request.subject_id)

            # 日期范围筛选
            if request.start_date:
                query = query.filter(StudyCheckIn.check_in_date >= request.start_date)
            if request.end_date:
                query = query.filter(StudyCheckIn.check_in_date <= request.end_date)

            # 心情筛选
            if request.mood:
                query = query.filter(StudyCheckIn.mood == request.mood)

            # 计算总数
            total = query.count()

            # 分页查询
            page_size = min(request.page_size, 100)  # 最大100条
            offset = (request.page - 1) * page_size
            check_ins = query.order_by(
                StudyCheckIn.check_in_date.desc()
            ).limit(page_size).offset(offset).all()

            # 转换为字典列表（列表不返回完整内容）
            check_ins_data = [check_in.to_dict(include_content=False) for check_in in check_ins]

            # 构建分页结果
            result_data = {
                'items': check_ins_data,
                'total': total,
                'page': request.page,
                'page_size': page_size,
                'total_pages': (total + page_size - 1) // page_size
            }

            return Result.success(data=result_data)

        except Exception as e:
            return Result.internal_error(f'查询失败：{str(e)}')

        finally:
            db.close()

    # ==================== 统计相关方法 ====================

    @staticmethod
    def get_statistics_summary(user_id: int, subject_id: Optional[int] = None) -> Result:
        """
        获取统计汇总数据
        目的：提供用户的学习统计概览
        功能：计算总打卡天数、总时长、当前连续天数、最长连续天数等

        Args:
            user_id (int): 用户ID
            subject_id (Optional[int]): 科目ID，None表示全部科目

        Returns:
            Result: 统一响应结果对象
        """
        db: Session = SessionLocal()

        try:
            # 构建查询条件
            query = db.query(StudyCheckIn).filter(
                StudyCheckIn.user_id == user_id,
                StudyCheckIn.status == 1
            )

            if subject_id:
                query = query.filter(StudyCheckIn.subject_id == subject_id)

            # 总打卡天数（去重统计日期）
            total_days = query.with_entities(
                func.count(func.distinct(StudyCheckIn.check_in_date))
            ).scalar() or 0

            # 总学习时长（分钟）
            total_duration = query.with_entities(
                func.sum(StudyCheckIn.duration_minutes)
            ).scalar() or 0

            # 当前连续打卡天数
            today = get_db_today()
            continuous_days = StudyService._calculate_current_continuous_days(
                db, user_id, subject_id, today
            )

            # 最大连续打卡天数
            max_continuous_days = StudyService._calculate_max_continuous_days(
                db, user_id, subject_id
            )

            # 本周打卡天数
            week_start = today - timedelta(days=today.weekday())
            week_days = query.filter(
                StudyCheckIn.check_in_date >= week_start
            ).with_entities(
                func.count(func.distinct(StudyCheckIn.check_in_date))
            ).scalar() or 0

            # 本月打卡天数
            month_start = today.replace(day=1)
            month_days = query.filter(
                StudyCheckIn.check_in_date >= month_start
            ).with_entities(
                func.count(func.distinct(StudyCheckIn.check_in_date))
            ).scalar() or 0

            summary = {
                'total_days': total_days,
                'total_duration': total_duration,
                'continuous_days': continuous_days,
                'max_continuous_days': max_continuous_days,
                'week_days': week_days,
                'month_days': month_days
            }

            return Result.success(data=summary)

        except Exception as e:
            return Result.internal_error(f'统计失败：{str(e)}')

        finally:
            db.close()

    @staticmethod
    def _calculate_current_continuous_days(db: Session, user_id: int,
                                          subject_id: Optional[int], current_date: date) -> int:
        """
        计算当前连续打卡天数（内部方法）
        目的：从今天开始往前推算，计算连续打卡了多少天
        功能：如果今天没打卡，则从昨天开始算

        Args:
            db (Session): 数据库会话
            user_id (int): 用户ID
            subject_id (Optional[int]): 科目ID
            current_date (date): 当前日期

        Returns:
            int: 当前连续打卡天数
        """
        continuous_days = 0
        check_date = current_date

        while True:
            query = db.query(StudyCheckIn).filter(
                StudyCheckIn.user_id == user_id,
                StudyCheckIn.check_in_date == check_date,
                StudyCheckIn.status == 1
            )

            if subject_id:
                query = query.filter(StudyCheckIn.subject_id == subject_id)

            exists = query.first()

            if exists:
                continuous_days += 1
                check_date -= timedelta(days=1)
            elif continuous_days == 0:
                # 如果今天没打卡，从昨天开始算
                check_date -= timedelta(days=1)
                continue
            else:
                break

        return continuous_days

    @staticmethod
    def _calculate_max_continuous_days(db: Session, user_id: int,
                                      subject_id: Optional[int]) -> int:
        """
        计算最大连续打卡天数（内部方法）
        目的：查找历史记录中最长的连续打卡天数
        功能：遍历所有打卡记录，找出最长连续区间

        Args:
            db (Session): 数据库会话
            user_id (int): 用户ID
            subject_id (Optional[int]): 科目ID

        Returns:
            int: 最大连续打卡天数
        """
        query = db.query(StudyCheckIn.check_in_date).filter(
            StudyCheckIn.user_id == user_id,
            StudyCheckIn.status == 1
        )

        if subject_id:
            query = query.filter(StudyCheckIn.subject_id == subject_id)

        # 获取所有打卡日期并去重排序
        dates = [row[0] for row in query.distinct().order_by(StudyCheckIn.check_in_date).all()]

        if not dates:
            return 0

        max_continuous = 1
        current_continuous = 1

        for i in range(1, len(dates)):
            # 如果日期连续（相差1天）
            if (dates[i] - dates[i-1]).days == 1:
                current_continuous += 1
                max_continuous = max(max_continuous, current_continuous)
            else:
                current_continuous = 1

        return max_continuous

    @staticmethod
    def get_calendar_data(request: GetCalendarRequest) -> Result:
        """
        获取日历热力图数据
        目的：提供类似GitHub贡献图的打卡日历数据
        功能：按日期统计打卡次数，用于前端展示热力图

        Args:
            request (GetCalendarRequest): 日历数据请求对象

        Returns:
            Result: 统一响应结果对象，包含日历数据
        """
        db: Session = SessionLocal()

        try:
            # 确定日期范围
            if request.month:
                # 查询指定月份
                start_date = date(request.year, request.month, 1)
                if request.month == 12:
                    end_date = date(request.year + 1, 1, 1) - timedelta(days=1)
                else:
                    end_date = date(request.year, request.month + 1, 1) - timedelta(days=1)
            else:
                # 查询整年
                start_date = date(request.year, 1, 1)
                end_date = date(request.year, 12, 31)

            # 构建查询
            query = db.query(
                StudyCheckIn.check_in_date,
                func.count(StudyCheckIn.id).label('count'),
                func.sum(StudyCheckIn.duration_minutes).label('duration')
            ).filter(
                StudyCheckIn.user_id == request.user_id,
                StudyCheckIn.check_in_date >= start_date,
                StudyCheckIn.check_in_date <= end_date,
                StudyCheckIn.status == 1
            )

            if request.subject_id:
                query = query.filter(StudyCheckIn.subject_id == request.subject_id)

            # 按日期分组
            calendar_data = query.group_by(StudyCheckIn.check_in_date).all()

            # 转换为字典格式
            result_data = [
                {
                    'date': row[0].isoformat(),
                    'count': row[1],
                    'duration': row[2] or 0
                }
                for row in calendar_data
            ]

            return Result.success(data=result_data)

        except Exception as e:
            return Result.internal_error(f'查询失败：{str(e)}')

        finally:
            db.close()
